namespace GGF
{
    namespace API
    {
        using System;
        using System.Collections.Generic;

        /// <summary>
        /// Static class containing private, static, categorized collections of
        /// API method and parameter names. Used to enforce request integrity.
        /// Five enumerations are defined here. Four start with a different
        /// integer (in relation to the other three) to prevent overlap and possible
        /// usage of incorrect method or parameter value in specific contexts.
        /// </summary>
        public static class gElement
        {
            #region Fields

            private static List<Dictionary<int, string>> elementTypes;
            private static Dictionary<int, string> itemMethod;
            private static Dictionary<int, string> itemParam;
            private static Dictionary<int, string> listMethod;
            private static Dictionary<int, string> listParam;

            #endregion Fields

            #region Constructors

            static gElement()
            {
                itemMethod = new Dictionary<int, string>();
                itemMethod.Add((int)enumItemMethod.mark_completed, "mark_completed");
                itemMethod.Add((int)enumItemMethod.mark_incomplete, "mark_incomplete");
                itemMethod.Add((int)enumItemMethod.update, "update");
                itemMethod.Add((int)enumItemMethod.delete, "delete");

                listMethod = new Dictionary<int, string>();
                listMethod.Add((int)enumListMethod.get_all, "get_all");
                listMethod.Add((int)enumListMethod.create, "create");
                listMethod.Add((int)enumListMethod.update, "update");
                listMethod.Add((int)enumListMethod.delete, "delete");

                itemParam = new Dictionary<int, string>();
                itemParam.Add((int)enumItemParam.note, "note");
                itemParam.Add((int)enumItemParam.details, "details");
                itemParam.Add((int)enumItemParam.date_due, "date_due");
                itemParam.Add((int)enumItemParam.priority, "priority");

                listParam = new Dictionary<int, string>();
                listParam.Add((int)enumListParam.name, "name");
                listParam.Add((int)enumListParam.description, "description");
                listParam.Add((int)enumListParam.filter_status, "filter_status");

                elementTypes = new List<Dictionary<int, string>>();
                elementTypes.Add(itemMethod);
                elementTypes.Add(listMethod);
                elementTypes.Add(itemParam);
                elementTypes.Add(listParam);
            }

            #endregion Constructors

            #region Enumerations

            /// <summary>
            /// Enumeration representing the four element types used in gubb API
            /// transactions, starting from 0: method for an item, method for
            /// a list, parameter for an item method and parameter for a list
            /// method.
            /// </summary>
            public enum elementType
            {
                /// <summary>
                /// Value representing a method for an item.
                /// </summary>
                itemMethod,

                /// <summary>
                /// Value representing a method for a list.
                /// </summary>
                listMethod,

                /// <summary>
                /// Value representing a parameter for an item method.
                /// </summary>
                itemParam,

                /// <summary>
                /// Value representing a parameter for a list method.
                /// </summary>
                listParam
            }

            /// <summary>
            /// Enumeration representing the four supported API methods
            /// for items, starting at 0: <c>mark_completed</c> (0), <c>mark_incomplete</c> (1), <c>update</c> (2), and <c>delete</c> (3).
            /// </summary>
            public enum enumItemMethod
            {
                /// <summary>
                /// Marking an Item as Completed (http://gubb.net/api/docs)
                /// </summary>
                mark_completed,

                /// <summary>
                /// Marking an Item as Incomplete (http://gubb.net/api/docs)
                /// </summary>
                mark_incomplete,

                /// <summary>
                /// Updating an Existing Item (http://gubb.net/api/docs)
                /// </summary>
                update,

                /// <summary>
                /// Deleting an Item (http://gubb.net/api/docs)
                /// </summary>
                delete
            }

            /// <summary>
            /// Enumeration representing the four supported parameters for API methods
            /// dealing with items, starting at 8: 
            /// <c>note</c> (8), <c>details</c> (9), <c>date_due</c> (10), <c>priority</c> (11), and <c>list_id</c> (12).
            /// </summary>
            public enum enumItemParam
            {
                /// <summary>
                /// (http://gubb.net/api/docs)
                /// </summary>
                note = 8,

                /// <summary>
                /// (http://gubb.net/api/docs)
                /// </summary>
                details,

                /// <summary>
                /// (http://gubb.net/api/docs)
                /// </summary>
                date_due,

                /// <summary>
                /// Empty, 1, 2 or 3 where the numbers indicate the number of stars gubb uses to represent priority (http://gubb.net/api/docs)
                /// </summary>
                priority,

                /// <summary>
                /// Unique integer id for the item's list (http://gubb.net/api/docs)
                /// </summary>
                list_id
            }

            /// <summary>
            /// Enumeration representing the four supported API methods
            /// for lists, starting at 4: <c>get_all</c> (4), <c>create</c> (5), <c>update</c> (6), and <c>delete</c> (7).
            /// </summary>
            public enum enumListMethod
            {
                /// <summary>
                /// Getting All of a User's Lists (with or without items) (http://gubb.net/api/docs)
                /// </summary>
                get_all = 4,

                /// <summary>
                /// Creating a New List (http://gubb.net/api/docs)
                /// </summary>
                create,

                /// <summary>
                /// Updating an Existing List (http://gubb.net/api/docs)
                /// </summary>
                update,

                /// <summary>
                /// Deleting a List (http://gubb.net/api/docs)
                /// </summary>
                delete
            }

            /// <summary>
            /// Enumeration representing the three supported parameters for API methods
            /// dealing with lists, starting at 12: 
            /// <c>name</c> (13), <c>description</c> (14), and <c>filter_status</c> (15).
            /// </summary>
            public enum enumListParam
            {
                /// <summary>
                /// Name of the list (http://gubb.net/api/docs)
                /// </summary>
                name = 13,

                /// <summary>
                /// The description, if any, for the list (http://gubb.net/api/docs)
                /// </summary>
                description,

                /// <summary>
                /// one of [all, archived, incomplete, active_completed]. The "all" value is a special
                /// one, it overrides all other filter_* parameters and ensures the the method call will
                /// return all items for the list(s). (http://gubb.net/api/docs)
                /// </summary>
                filter_status

            }

            #endregion Enumerations

            #region Methods

            /// <summary>
            /// Returns correct element (list/item method or parameter) as a string
            /// for use in gubb HTTP request.
            /// <remarks>
            /// This method basically does indexing twice. First, the correct sub-collection
            /// is returned from the <c>elementTypes</c> collection using the first parameter.
            /// The correct list/item method or parameter name is then returned from that sub-collection.
            /// </remarks>
            /// </summary> 
            /// <param name="eType">A member of the <c>elementType</c> enumeration
            /// that tells us which of the four other enumerations to look
            /// into for our desired element, which is given by the second parameter to this method.</param>
            /// <param name="e">A standard .NET integer that represents the user's
            /// desired element in one of the following enumerations: <see cref="GGF.API.gElement.enumItemMethod"/>,
            /// <see cref="GGF.API.gElement.enumItemParam"/>,
            /// <see cref="GGF.API.gElement.enumListMethod"/>,
            /// or <see cref="GGF.API.gElement.enumListParam"/>.
            /// </param>
            /// <returns>A standard .NET string with the correct method/parameter name
            /// complying with the gubb API.</returns>
            /// <exception cref="System.Collections.Generic.KeyNotFoundException">Thrown
            /// when user passes an integer that does not correspond to a key in the
            /// relevant element collection.
            /// </exception>
            public static string getElement(elementType eType, int e)
            {
                string str;

                try
                {
                    str = (elementTypes[(int)eType])[e];
                }
                catch (KeyNotFoundException exc)
                {
                    Console.WriteLine("Integer {0} does not represent supported list method", e);
                    Console.WriteLine();
                    Console.WriteLine(exc.StackTrace);
                    Console.WriteLine(exc.Message);

                    throw;
                }

                return str;
            }

            #endregion Methods

        }
    }
}